﻿/*
 * MiniFox.Desktop v3.0.0
 * Docs & License: http://hanko12.com
 * (c) 2019 漢口十二
 */

+function (global, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['jquery'], factory);
    }
    else {
        var $ = jQuery || require('jquery');
        if (typeof exports === 'object' && typeof module !== 'undefined') {
            module.exports = factory($);
        }
        else {
            global.MiniFox = global.MiniFox || {};
            global.MiniFox.Desktop = factory($);
        }
    }
}(this, function ($) {
    "use strict";
    const fixedWidth = 220;
    const popupWidth = 40;
    const screenCritical = 768;

    var Desktop = (function () {

        var desktop = MiniFox.extend(MiniFox.Container, function () {

            +function (desktop) {
                Object.defineProperty(desktop, "$miniWindow", {
                    configurable: false,
                    enumerable: false,
                    get: function () {
                        return desktop.width() < screenCritical;
                    }
                });
                
            }(this);
        });
        desktop.prototype.init = function () {
            var relayout = MiniFox.debounce(function () {
                this.layout();
            });
            var changeHead = MiniFox.debounce(function () {
                this.$head.update();
            });
            var changeMenu = MiniFox.debounce(function () {
                this.$main.$menu.update();
            });
            var changeHome = MiniFox.debounce(function () {
                this.$main.$workspace.changeHome();
            });
            var changeFoot = MiniFox.debounce(function () {
                this.$foot.update();
            });
            this.watcher = {
                $miniWindow: { onchange: null },
                fixedWidth: { onchange: null },
                popupWidth: { onchange: null },
                fixedMenu: { onchange: null },
                iconUri: { onchange: relayout },
                theme: { onchange: relayout },
                title: { onchange: relayout },
                shortcuts: {onchange: relayout },
                logoUri: { onchange: changeHead },
                channels: { onchange: changeHead },
                navItems: { onchange: changeHead },
                homeUri: { onchange: changeHome },
                signOutUri: { onchange: changeHead },
                profilesItems: { onchange: changeHead },
                currentUser: { onchange: changeHead },
                qrCodeModule: { onchange: changeHead },
                applicationId: { onchange: changeHead },
                multipleChannel: { onchange: changeHead },
                menuItems: { onchange: changeMenu },
                appDescription: { onchange: changeFoot },
                versionDescription: { onchange: changeFoot }
            };
        };
        desktop.prototype.mergeOptions = function (options) {
            var defaults = {
                fixedMenu: true,
                fixedWidth: fixedWidth,
                popupWidth: popupWidth,
                theme: "default",
                currentUser: {},
                host: "",
                baseUri: "",
                title: "",
                iconUri: "",
                logoUri: "",
                applicationId: "",
                multipleChannel: false,
                channels: [],
                menuItems: [],
                navItems: [],
                shortcuts: [],
                homeUri: "",
                appDescription: "",
                versionDescription: ""
            }
            return $.extend({}, defaults, options);
        };
        desktop.prototype.createComponents = function () {
            var components = this.$options.components;
            
            for (var name in this.watcher) {
                MiniFox.recursion(this.$options, "components", name, true);
            }

            this.$head = this.components.head = new HeadContainer(components.head, this);
            this.$main = this.components.main = new MainContainer(components.main, this);
            this.$foot = this.components.foot = new FootContainer(components.foot, this);
            +function (container) {

                for (var name in container.watcher) {
                    MiniFox.recursion(container, "components", name, false);
                }

            }(this);
        };
        desktop.prototype.domInit = function () {
            var workspace = this.$main.$workspace;
            this.$element.delegate("a[data-target='module'][data-url]", "click", workspace, function (e) {
                var workspace = e.data;
                var moduleId = $(this).attr("data-val");
                var openMode = $(this).attr("data-open");
                var icon = $(this).attr("data-icon");
                var url = $(this).attr("data-url");
                var title = $(this).prop("title");
                switch (openMode) {
                    case "NewWindow":
                        window.open(url);
                        break;
                    case "Dialog":
                        //对话框
                        break;
                    default:
                        workspace.openTab(url, title, icon);
                        break;
                }
                return false;
            });

            var resize = (function (context) {
                return function () { context.resize(); };
            })(this);

            $(window).resize(MiniFox.debounce(resize));

            window.addEventListener('message', (function (desktop) {
                return function (e) {
                    var channels = desktop.channels;
                    if (e && e.data) {
                        if (e.origin === (window.location.protocol + "//" + window.location.host) || channels.any(function (channel) { return channel.FullHost === e.origin; })) {

                            var data = e.data;
                            var objName = data.objectName;
                            var methodName = data.methodName;
                            var args = data.arguments;
                            var obj = objName ? desktop[objName] : desktop;
                            var method = obj[methodName];
                            if (method && $.isFunction(method))
                                method.apply(obj, args);
                        }
                    }
                };
            })(this), false);

        };

        desktop.prototype.layout = function () {

            if (this.title) {
                if ($('head title').length > 0) {
                    $('head title').text(this.title);
                }
                else {
                    $('<title>' + this.title + '</title>').appendTo(document.head);
                }
            }
            if (this.iconUri) {
                if ($("head link[rel='shortcut icon']").length > 0) {
                    $("head link[rel='shortcut icon']").prop("href", this.iconUri);
                }
                else {
                    $('<link href="' + this.iconUri + '" rel="shortcut icon" />').appendTo(document.head);
                }
            }

            if ($("head #theme").length > 0) {
                $("head #theme").prop("href", "/static/css/themes/" + this.theme + ".css");
            }
            else {
                $('<link id="theme" href="/static/css/themes/' + this.theme + '.css" rel="stylesheet" />').appendTo(document.head);
            }

        };

        desktop.prototype.changeChannel = function (id) {

            this.applicationId = id;
            if ($.isFunction(this.getMenuData)) {
                this.getMenuData(id);
                //var promise = this.getMenuData(id);
                //if (promise) {
                //    var desktop = this;
                    
                //    promise.then(function (data) {
                //        desktop.applicationId = data.ApplicationID;
                //        desktop.navItems = data.NavItems;
                //        desktop.menuItems = data.MenuItems;
                //    });
                //}
            }
            if ($.isFunction(this.getNavData)) {
                this.getNavData(id);
            }
        };

        desktop.prototype.change = function (data) {
            this.theme = data.theme;
            this.title = data.title;
            this.logoUri = data.logoUri;
            this.iconUri = data.iconUri;
            this.homeUri = data.homeUri;
            this.appDescription = data.description;
            this.versionDescription = data.copyRight;
        };

        desktop.prototype.reloadHome = function () {
            if (this.homeUri) {
                var uri = this.homeUri.toUri();
                uri.addParam('_', Math.random());
                this.homeUri = uri.toString();
            }
            else {
                if (this.portlet) {

                    this.portlet.clearWidgets();
                    this.portlet.created();
                }
            }
        };

        desktop.prototype.enter = function (url, title, icon, openMode) {
            if (openMode) {
                switch (openMode) {
                    case "1":
                        window.open(url);
                        break;
                    case "2":
                        //对话框
                        break;
                    default:
                        this.$main.$workspace.openTab(url, title, icon);
                        break;
                }
            }
            else {
                this.$main.$workspace.openTab(url, title, icon);
            }
        };

        desktop.prototype.exit = function (url) {

            this.$main.$workspace.closeTab(url);
        };

        return desktop;
    })();

    var HeadContainer = (function () {
        var container = MiniFox.extend(MiniFox.Container, function () {
        });

        container.prototype.domInit = function () {

            this.$element.delegate("a[data-target='menubar'][data-toggle='slide']", "click", (function (container) {
                return function () {
                    var main = container.$parent.$main;
                    var toggle = !container.fixedMenu;
                    main.toggleMenu(toggle);
                    if (toggle) {
                        $(this).find('.glyphicon').removeClass('glyphicon-list').addClass('glyphicon-align-justify');
                    }
                    else {
                        $(this).find('.glyphicon').removeClass('glyphicon-align-justify').addClass('glyphicon-list');
                    }
                    container.fixedMenu = toggle;
                };
            })(this));

            this.$element.delegate("a[data-target='channel']", "click", (function (desktop) {

                return function () {
                    var id = $(this).attr("data-val");
                    $(this).addClass("actived").parent().siblings().find(">a").removeClass("actived");
                    desktop.changeChannel(id);
                    return false;
                };
            })(this.$parent));

            var hover = function () {
                $(this).find('.dropdown-menu').empty();
                var channelItems = $(this).siblings();
                var hiddenItems = channelItems.filter(':hidden');
                var moreItems = hiddenItems.clone().show().appendTo($(this).find('.dropdown-menu'));
                moreItems.find("a[data-val]").click(function () {

                    $(this).addClass("actived").parent().siblings().find(">a").removeClass("actived");
                    var dataVal = $(this).attr("data-val");
                    var channel = hiddenItems.find(" >a[data-val='" + dataVal + "']");
                    channel.click();
                });
                $(this).find('.dropdown-menu').show();
            };
            var unhover = function () {
                var dropdown = $(this).find('.dropdown-menu');
                dropdown.hide();
            }

            this.$element.delegate(".navbar .nav-channel .navbar-nav > .more", "mouseenter", hover);

            this.$element.delegate(".navbar .nav-channel .navbar-nav > .more", "mouseleave", unhover);

            this.$element.delegate(".minibar .togglebar", "click", function () {
                var selector = $(this).attr("data-target");
                if ($(selector).is(":hidden")) {
                    $(selector).siblings().slideUp("normal", function () { $(selector).slideDown(); }); 
                }
                else {
                    $(selector).slideUp();
                }
            })
        };

        container.prototype.layout = function () {
            var height = this.height();
            var width = this.$element.find(".navbar").innerWidth();
            var taskWidth = this.$element.find(".navbar .nav-task").outerWidth() + 20;
            var channelWrap = this.$element.find(".navbar .nav-channel");
            var channelItems = channelWrap.find(".navbar-nav > li:not(.more)");
            var channelMore = channelWrap.find(".navbar-nav > .more");

            channelWrap.css({ 'width': 'calc( 100% - ' + taskWidth + 'px )' });
            channelWrap.height(height);

            channelWrap.css({ 'overflow': 'hidden' });
            channelItems.show();
            channelMore.hide();

            if (channelWrap.height() < channelWrap[0].scrollHeight) {
                channelMore.show();
                this.hideItems(channelWrap, channelItems);
                channelWrap.css({ 'overflow': 'visible' });
            }


        };

        container.prototype.hideItems = function (container, items) {
            if (items.length === 0) return;

            items.last().hide();
            if (container.height() < container[0].scrollHeight) {
                this.hideItems(container, items.not(':last'));
            }
        };

        //container.prototype.setData = function (dataItems) {
        //    this.navItems = dataItems;
        //};

        return container;
    })();

    var MainContainer = (function () {

        var container = MiniFox.extend(MiniFox.Container, function () {

        });
        container.prototype.createComponents = function () {

            this.$menu = this.components.menubar = new MenuContainer(this.$options.components.menubar, this);
            this.$workspace = this.components.workspace = new WorkSpaceContainer(this.$options.components.workspace, this);
        };
        container.prototype.domInit = function () {
            this.$element.delegate("li a[data-target='folder']", "click", this, function (e) {
                var container = e.data;
                if (container.fixedMenu) {
                    var sub = $(this).next("ul:first");
                    if (sub.is(":hidden")) {
                        $(this).find(".pull-right").removeClass("fa-angle-right").addClass("fa-angle-down");
                        sub.slideDown();
                    }
                    else {
                        $(this).find(".pull-right").removeClass("fa-angle-down").addClass("fa-angle-right");
                        sub.slideUp();
                    }
                }
                return false;
            });

            this.$element.delegate("li a[data-target='module']", "click", this.$workspace, function (e) {
                var workspace = e.data;
                var moduleId = $(this).attr("data-val");
                var icon = $(this).attr("data-icon");
                var url = $(this).attr("data-url");
                var title = $(this).prop("title");
                workspace.openTab(url, title, icon);
                return false;
            });

        };
        container.prototype.toggleMenu = function (tofixed) {
            var fixedWidth = this.fixedWidth;
            var popupWidth = this.popupWidth;
            var menuElement = this.$menu.$element;
            var workspaceElement = this.$workspace.$element;
            if (this.$miniWindow) {

                if (tofixed) {
                    menuElement.animate({ "width": fixedWidth }, "normal").show();
                }
                else {
                    menuElement.animate({ "width": 0 }, "normal", function () { $(this).hide() });
                    menuElement.find(".sub:not(:hidden)").prev().click();
                }
            }
            else {
                if (tofixed) {
                    menuElement.removeClass('popup').addClass('fixed').animate({ "width": fixedWidth }, "normal");
                    workspaceElement.animate({ "margin-left": fixedWidth }, "normal");
                }
                else {
                    menuElement.find(".sub:not(:hidden)").prev().click();

                    menuElement.removeClass('fixed').addClass('popup').animate({ "width": popupWidth }, "normal");
                    workspaceElement.animate({ "margin-left": popupWidth });
                }
            }
        };

        container.prototype.layout = function () {

            var fixedWidth = this.fixedWidth;
            var popupWidth = this.popupWidth;
            var menuElement = this.$menu.$element;
            var workspaceElement = this.$workspace.$element;

            menuElement.height(this.height());
            if (this.$miniWindow) {
                workspaceElement.css("margin", 0);
                if (this.fixedMenu) {
                    menuElement.removeClass('popup').addClass('fixed').css({ "width": fixedWidth }).show();
                    this.$parent.$element.find("a[data-target='menubar'][data-toggle='slide']").click();
                }
                else {
                    menuElement.removeClass('popup').addClass('fixed').css({ "width": 0 }).hide();
                }
            }
            else {
                workspaceElement.css("margin-left", this.fixedMenu ? fixedWidth : popupWidth);
                if (this.fixedMenu) {
                    menuElement.removeClass('popup').addClass('fixed').css({ "width": fixedWidth }).show();
                }
                else {
                    menuElement.removeClass('fixed').addClass('popup').css({ "width": popupWidth }).show();
                }
            }
        };

        return container;
    })();

    var MenuContainer = (function () {
        var container = MiniFox.extend(MiniFox.Container, function () {

        });
        container.prototype.domInit = function () {

        };
        container.prototype.layout = function () {

        };
        //container.prototype.setData = function (dataItems) {
        //    this.menuItems = dataItems;
        //};
        return container;
    })();

    var WorkSpaceContainer = (function () {
        var container = MiniFox.extend(MiniFox.Container, function () {
            this.getTabItemContainer = function () {
                return this.$element.find(".tabs-container .tabitems-wrap .nav-tabs");
            };
            this.getTabItemScroller = function () {
                return this.$element.find(".tabs-container .tabs-scroller .nav-tabs-scroller");
            };
            this.getTabPageContainer = function () {
                return this.$element.find(".tabpages-container");
            };
        });
        container.prototype.domInit = function () {

            this.$parent.$element.delegate("a[href='#home']", "click", this, function (e) {
                var workspace = e.data;
                var tabItemContainer = workspace.getTabItemContainer();
                var tabPageContainer = workspace.getTabPageContainer();
                tabPageContainer.find(".content").removeClass("current");
                tabItemContainer.find("li").removeClass("active");
                workspace.$element.find(".tabpages-container .home").addClass("current");

            });
            this.$parent.$element.delegate(".tabs-container .tabitems-wrap .nav-tabs li", "click", this, function (e) {
                var workspace = e.data;
                var tabPageContainer = workspace.getTabPageContainer();
                var li = $(this).addClass("active");
                li.siblings().removeClass("active");
                var url = li.attr("page-url");
                var current = tabPageContainer.find(".content[page-url='" + url + "']");
                var others = current.siblings();
                others.removeClass("current");
                var current = current.addClass("current");
            });

            this.$parent.$element.delegate(".tabs-container .tabitems-wrap .nav-tabs li a .remove", "click", this, function (e) {
                var workspace = e.data;
                var tabItemContainer = workspace.getTabItemContainer();
                var tabPageContainer = workspace.getTabPageContainer();

                var li = $(this).parent().parent();
                var url = li.attr("page-url");
                var tabpage = tabPageContainer.find(".content[page-url='" + url + "']");
                var actived = li.hasClass("active");
                tabpage.remove();
                li.remove();
                if (actived) {
                    if (tabItemContainer.children().size() > 0)
                        tabItemContainer.children().last().click();
                    else
                        $("a[href='#home']").click();
                }
                workspace.tabScrolled();
            });

            this.$parent.$element.delegate(".tabs-container .tabs-scroller a[data-target]", "click", this, function (e) {
                var target = $(this).attr("data-target");
                e.data[target]();
            });

        };

        container.prototype.layout = function () {

        };
        container.prototype.changeHome = function () {
            this.$element.find("#home").prop("src", this.homeUri);
        };
        container.prototype.tabScrolled = function () {
            var tabItemScroller = this.getTabItemScroller();
            var tabItemContainer = this.getTabItemContainer();
            var scrollerLeft = tabItemScroller.find("a[data-target='tabScrollLeft']");
            var scrollerRight = tabItemScroller.find("a[data-target='tabScrollRight']");
            var left = tabItemContainer.position().left;
            var maxwidth = tabItemContainer.parent().innerWidth();
            var width = 0;
            tabItemContainer.find("li").each(function () {
                width += $(this).outerWidth();
            });
            if (left >= 0) {
                scrollerLeft.removeClass("enabled");
            }
            else {
                scrollerLeft.addClass("enabled");
            }
            var gap = maxwidth - width;
            if (left <= gap) {
                scrollerRight.removeClass("enabled");
            }
            else {
                scrollerRight.addClass("enabled");
            }
        };

        container.prototype.tabScrollLeft = function () {
            var container = this;
            var tabItemScroller = this.getTabItemScroller();
            var tabItemContainer = this.getTabItemContainer();
            var left = tabItemContainer.position().left;
            if (left < 0) {
                left += 200;
                if (left >= 0) {
                    left = 0;
                }
                tabItemContainer.stop().animate({ "left": left }, "fast", function () { container.tabScrolled(); });

            }
        };

        container.prototype.tabScrollRight = function () {
            var container = this;
            var tabItemScroller = this.getTabItemScroller();
            var tabItemContainer = this.getTabItemContainer();
            var left = tabItemContainer.position().left;
            var maxwidth = tabItemContainer.parent().innerWidth();
            var width = 0;
            tabItemContainer.find("li").each(function () {
                width += $(this).outerWidth();
            });
            var gap = maxwidth - width;
            if (left > gap) {
                tabItemContainer.stop().animate({ "left": (left - 200) }, "fast", function () { container.tabScrolled(); });
            }
        };

        container.prototype.closeOthers = function () {

            this.$element.find(".tabs-container .nav-tabs li:not(.active) a .remove").click();
        };

        container.prototype.clearTab = function () {

            this.$element.find(".tabs-container .nav-tabs li a .remove").click();
        };

        container.prototype.openTab = function (url, title, icon) {
            if (!url || typeof url !== "string")
                return;

            url = MiniFox.resolveFullPath(url);
            icon = (icon ? icon : 'fa-edit');
            title = (title ? title : '标签页');

            var tabItemContainer = this.getTabItemContainer();
            var tabPageContainer = this.getTabPageContainer();

            var tabitem = tabItemContainer.find("li[page-url='" + url + "']");
            if (tabitem.length <= 0) {
                var itemData = { url: url, title: title, icon: icon };
                var tabitem = $(this.tabItemTemplate).tmpl(itemData);
                tabitem.appendTo(tabItemContainer);

                var tabpage = $(this.tabPageTemplate).tmpl(itemData);
                tabpage.appendTo(tabPageContainer);

                this.tabScrolled();
                tabpage.find("iframe").load({ url: url, icon: icon, title: title }, function (e) {

                    var icon = e.data.icon;
                    try {
                        if ("about:blank" == this.contentWindow.location.href.toLowerCase())
                            return;

                        var uri = this.contentWindow.location.pathname.toLowerCase();

                        if (uri.indexOf("oauth2/signin") >= 0) {
                            var return_url = e.data.url;
                            var rootUrl = "/";

                            window.location.href = rootUrl + (rootUrl.indexOf("?") < 0 ? "?" : "&") + "target=" + return_url + "&icon=" + icon;
                        }
                        else {
                            var title = e.data.title;
                            if (title != this.contentWindow.document.title) {
                                title = this.contentWindow.document.title;
                            }
                            if (title) {
                                tabitem.find(".title").text(" " + title + " ").prop("title", title);
                            }
                        }
                    }
                    catch (e) {
                        console.log(e);
                    }
                    tabitem.find(".fa-circle-o-notch").removeClass("fa-circle-o-notch").removeClass("fa-spin").addClass(icon);
                });
            }
            tabitem.click();
        };

        container.prototype.closeTab = function (url) {
            if (!url)
                return;

            var tabItemContainer = this.getTabItemContainer();

            var tabitem = tabItemContainer.find("li[page-url='" + url + "']");
            if (tabitem.length > 0) {
                tabitem.find(">a .remove").click();
            }
        };

        return container;
    })();

    var FootContainer = (function () {
        var container = MiniFox.extend(MiniFox.Container, function () {
        });

        container.prototype.layout = function () {

        };

        return container;
    })();

    return Desktop;
});